package com.whc.gulimall.authserver.controller;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpException;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.whc.common.constant.SmsConstant;
import com.whc.common.constant.SocialLoginConstant;
import com.whc.common.utils.R;
import com.whc.common.vo.SocialResponseVo;
import com.whc.gulimall.authserver.feign.MemberFeign;
import com.whc.gulimall.authserver.feign.SmsFeign;
import com.whc.gulimall.authserver.vo.LoginVo;
import com.whc.gulimall.authserver.vo.RegisterVo;
import com.whc.gulimall.authserver.vo.SocialUserVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author angaoen
 */
@Controller
@Slf4j
public class LoginController {

    /**
     * 远程调用-发送验证码功能
     */
    @Resource
    private SmsFeign smsFeign;

    /**
     * RedisTemplate 的以字符串为中心的扩展
     */
    @Resource(name = "stringRedisTemplate")
    private StringRedisTemplate redisTemplate;

    /**
     * 会员-远程调用
     */
    @Resource
    private MemberFeign memberFeign;

    /**
     * 发送短信
     *
     * @param phoneNumber 手机号码
     * @return 统一返回结果
     */
    @GetMapping("/sms/sendCode")
    @ResponseBody
    public R sendCode(@RequestParam("phoneNumber") String phoneNumber) {
        smsFeign.sendMsg(phoneNumber);
        return R.ok();
    }

    /**
     * 注册用户
     *
     * @param vo                 用户信息
     * @param result             错误
     * @param redirectAttributes 绑定属性
     * @return 跳转地址
     */
    @PostMapping("/register")
    public String register(@Valid RegisterVo vo,
                           BindingResult result,
                           RedirectAttributes redirectAttributes) {
        if (result.hasErrors()) {
            Map<String, String> errors = result.getFieldErrors().stream()
                    .collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage));
            redirectAttributes.addFlashAttribute("errors", errors);
            return "redirect:http://auth.gulimall.com/reg.html";
        }

        // 能够进入此处，说明没有，验证验证码是否正确；
        String codeStr = redisTemplate.opsForValue().get(SmsConstant.SMS_PREFIX + vo.getPhone());
        // 判空
        if (StrUtil.isNotEmpty(codeStr)) {
            String code = codeStr.split("_")[0];
            // 验证码正确
            if (vo.getCode().equals(code)) {
                // 删除验证码
                redisTemplate.delete(SmsConstant.SMS_PREFIX + vo.getPhone());
                // 验证码通过
                R regist = memberFeign.register(vo);
                if (regist.getCode() == 0) {
                    // 注册成功
                    return "redirect:http://auth.gulimall.com/login.html";
                } else {
                    // 注册失败
                    Map<String, String> errors = new HashMap<>(1);
                    errors.put("msg", regist.getData(new TypeReference<String>() {
                    }));
                    redirectAttributes.addFlashAttribute("errors", errors);
                    return "redirect:http://auth.gulimall.com/reg.html";
                }
            }
        }
        Map<String, String> map = new HashMap<>(1);
        map.put("code", "验证码错误");
        redirectAttributes.addFlashAttribute("errors", map);
        return "redirect:http://auth.gulimall.com/reg.html";
    }

    /**
     * 登录
     *
     * @param vo                 vo
     * @param redirectAttributes 携带数据
     * @return 跳转
     */
    @PostMapping("/login")
    public String login(@RequestBody LoginVo vo, RedirectAttributes redirectAttributes) {
        R r = memberFeign.login(vo);
        if (r.getCode() == 0) {
            return "redirect:http://gulimall.com";
        }

        // 登陆失败
        Map<String, String> errors = new HashMap<>(1);
        errors.put("msg", r.getData("msg", new TypeReference<String>() {
        }));
        redirectAttributes.addFlashAttribute("errors", errors);
        return "redirect:http://auth.gulimall.com/login.html";
    }

    @GetMapping("/login.html")
    public String login(HttpSession session) {
        Object sessionAttribute = session
                .getAttribute(SocialLoginConstant.SOCIAL_LOGIN_CONSTANT);
        if (sessionAttribute == null) {
            return "login";
        }
        return "redirect:http://gulimall.com";
    }

    /**
     * 登录及回调信息
     *
     * @param code    用户登录之后新浪返回的code码
     * @param session session
     * @return 重定向
     */
    @GetMapping("/oauth2.0/weibo/success")
    public String login(@RequestParam("code") String code, HttpSession session) {
        /*
        在用户登陆后，获取到新浪返回的code码，使用code码作为参数
        调用https://api.weibo.com/oauth2/access_token
         */
        // 拼接请求参数
        String urlData = "client_id=3507575097" +
                "&client_secret=eabc11eaa1d41e6eb8c757bfb5c93c34" +
                "&grant_type=authorization_code" +
                "&redirect_uri=http://auth.gulimall.com/oauth2.0/weibo/success" +
                "&code=" + code;

        try {
            // 发送请求
            HttpResponse response = HttpRequest.post("https://api.weibo.com/oauth2/access_token?" + urlData).execute();
            if (response.getStatus() == 200) {
                SocialUserVo socialUserVo = JSON.parseObject(response.body(), new TypeReference<SocialUserVo>() {
                });
                R r = memberFeign.oathTwoLogin(socialUserVo);
                if (r.getCode() != 0) {
                    return "redirect:http://auth.gulimall.com/login.html";
                }
                session.setAttribute(SocialLoginConstant.SOCIAL_LOGIN_CONSTANT, r.getData(new TypeReference<SocialResponseVo>() {
                }));

                return "redirect:http://gulimall.com";
            }
        } catch (HttpException e) {
            return "redirect:http://auth.gulimall.com/login.html";
        }
        return "redirect:http://auth.gulimall.com/login.html";
    }
}
